<!DOCTYPE html>

<html lang="zh">

<head>
  <title>Example 02.04 - Geometries</title>
  <script src="https://cdn.bootcss.com/jquery/3.4.0/jquery.js"></script>
  <script src="https://cdn.bootcss.com/three.js/r83/three.js"></script>
  <script type="text/javascript" src="../libs/ParametricGeometries.js"></script>
  <script type="text/javascript" src="../libs/ConvexGeometry.js"></script>

  <script type="text/javascript" src="../libs/stats.js"></script>
  <script type="text/javascript" src="../libs/dat.gui.js"></script>
  <style>
    body {
      /* set margin to 0 and overflow to hidden, to go fullscreen */
      margin: 0;
      overflow: hidden;
    }
  </style>
</head>
<body>

<div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">

    window.onload = function () {
        var renderer = new THREE.WebGLRenderer()
        renderer.setClearColor(0xcccccc, 1)
        renderer.setSize(window.innerWidth, window.innerHeight)
        renderer.shadowMap.enabled = true

        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)

        var scene = new THREE.Scene()

        var axis = new THREE.AxisHelper(30)
        scene.add(axis)
        //
        var planeGeometry = new THREE.PlaneGeometry(60, 40)
        var planeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000})
        var plane = new THREE.Mesh(planeGeometry, planeMaterial)
        plane.receiveShadow = true
        plane.rotation.x = -0.5 * Math.PI
        plane.position.x = 0
        plane.position.y = 0
        plane.position.z = 0
        scene.add(plane)

        camera.position.x = -20
        camera.position.y = 25
        camera.position.z = 20
        camera.lookAt(scene.position)

        var spotLight = new THREE.SpotLight(0xffffff)
        spotLight.position.set(-40, 60, 10)
        spotLight.castShadow = true
        scene.add(spotLight)

        document.getElementById('WebGL-output').appendChild(renderer.domElement)

        var step = 0

        var vertices = [
            new THREE.Vector3(1, 3, 1),
            new THREE.Vector3(1, 3, -1),
            new THREE.Vector3(1, -1, 1),
            new THREE.Vector3(1, -1, -1),
            new THREE.Vector3(-1, 3, -1),
            new THREE.Vector3(-1, 3, 1),
            new THREE.Vector3(-1, -1, -1),
            new THREE.Vector3(-1, -1, 1)
        ]
        var faces = [
            new THREE.Face3(0, 2, 1),
            new THREE.Face3(2, 3, 1),
            new THREE.Face3(4, 6, 5),
            new THREE.Face3(6, 7, 5),
            new THREE.Face3(4, 5, 1),
            new THREE.Face3(5, 0, 1),
            new THREE.Face3(7, 6, 2),
            new THREE.Face3(6, 3, 2),
            new THREE.Face3(5, 7, 0),
            new THREE.Face3(7, 2, 0),
            new THREE.Face3(1, 3, 4),
            new THREE.Face3(3, 6, 4),
        ]

        var geom = new THREE.Geometry()
        geom.vertices = vertices
        geom.faces = faces
        geom.computeFaceNormals()

        var materials = [
            new THREE.MeshLambertMaterial({
                opacity: 0.6,
                color: 0x44ff44,
                transparent: true
            }),
            new THREE.MeshBasicMaterial({color: 0x000000, wireframe: true})
        ]

        var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, materials)
        mesh.children.forEach(function (e) {
            e.castShadow = true
        })
        scene.add(mesh)

        function addControl(x, y, z) {
            var controls = new function () {
                this.x = x
                this.y = y
                this.z = z
            }
            return controls
        }

        var controlPoints = []
        controlPoints.push(addControl(3, 5, 3));
        controlPoints.push(addControl(3, 5, 0));
        controlPoints.push(addControl(3, 0, 3));
        controlPoints.push(addControl(3, 0, 0));
        controlPoints.push(addControl(0, 5, 0));
        controlPoints.push(addControl(0, 5, 3));
        controlPoints.push(addControl(0, 0, 0));
        controlPoints.push(addControl(0, 0, 3));


        var gui = new dat.GUI()
        gui.add(new function(){
            this.clone = function(){
                var cloneGeometry = mesh.children[0].geometry.clone()
                var materials = [
                    new THREE.MeshLambertMaterial({opacity: 0.6, color: 0xff44ff, transparent: true}),
                    new THREE.MeshBasicMaterial({color: 0xffffff, wireframe: true})
                ]

                var mesh2 = THREE.SceneUtils.createMultiMaterialObject(cloneGeometry, materials)
                mesh2.children.forEach(function(e){e.castShadow = true})

                mesh2.translateX(5)
                mesh2.translateZ(5)
                mesh2.name = 'clone'
                scene.remove(scene.getChildByName('clone'))
                scene.add(mesh2)
            }
        }, 'clone')

        for(var i = 0; i< 8;i++){
            f1 = gui.addFolder('Vertices' + (i+1))
            f1.add(controlPoints[i], 'x', -10, 10);
            f1.add(controlPoints[i], 'y', -10, 10);
            f1.add(controlPoints[i], 'z', -10, 10);
        }


        function initStats() {
            var stats = new Stats()
            stats.setMode(0)
            stats.domElement.style.position = 'absolute'
            stats.domElement.style.top = '0'
            stats.domElement.style.left = '0'
            document.getElementById('Stats-output').appendChild(stats.domElement)
            return stats
        }

        var stats = initStats()

        function render() {
            stats.update()

            var vertices = []
            for(var i =0; i<8; i++){
                vertices.push(new THREE.Vector3(controlPoints[i].x, controlPoints[i].y, controlPoints[i].z))
            }
            mesh.children.forEach(function(e){
                e.geometry.vertices = vertices
                e.geometry.verticesNeedUpdate = true
                e.geometry.computeFaceNormals()
            })

            requestAnimationFrame(render)
            renderer.render(scene, camera)
        }

        render()

    }


</script>
</body>
</html>
